package org.bookr.console.controller;

import org.bookr.engine.model.Group;
import org.bookr.engine.model.Reader;
import org.bookr.engine.service.BookrService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

/**
 * @author Pawel Tomaszewski
 */
@Controller
public class ReaderController {
    private BookrService bookrService;
    private Logger logger = LoggerFactory.getLogger(ReaderController.class);

    @RequestMapping(value = "/reader/create", method = RequestMethod.GET)
    public ModelAndView createReaderForm() {
        ModelAndView result = new ModelAndView("console.createReader");
        result.addObject("status", "console.webapp.status.fillForm");
        result.addObject("reader", new Reader());
        result.addObject("allGroups", bookrService.listGroups());
        result.addObject("allComments", bookrService.listComments());
        return result;
    }

    @RequestMapping(value = "/reader/create", method = RequestMethod.POST)
    public ModelAndView processCreateReaderForm(@ModelAttribute Reader reader, BindingResult bindingResult) {
        ModelAndView results = new ModelAndView("console.createReader");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "firstName", "console.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "lastName", "console.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "username", "console.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "password", "console.webapp.formValidation.emptyField");
        if(bindingResult.hasErrors()) {
            results.addObject("status", "console.webapp.status.correctForm");
            results.addObject("allGroups", bookrService.listGroups());
            results.addObject("allComments", bookrService.listComments());
        } else {
            Date now = new Date();
            reader.setCreatedDate(now);
            reader.setLastUpdateDate(now);
            String id = bookrService.updateReader(reader);
            results.addObject("status", "console.webapp.status.createSuccess");
            results.addObject("reader", bookrService.loadReaderById(id));
            results.setViewName("console.reader");
        }
        return results;
    }

    @RequestMapping(value = "/reader/{id}/edit", method = RequestMethod.GET)
    public ModelAndView editReaderForm(@PathVariable String id) {
        ModelAndView results = new ModelAndView("console.editReader");
        results.addObject("status", "console.webapp.status.fillForm");
        results.addObject("reader", bookrService.loadReaderById(id));
        results.addObject("allGroups", bookrService.listGroups());
        results.addObject("allComments", bookrService.listComments());
        return results;
    }

    @RequestMapping(value = "/reader/{id}/edit", method = RequestMethod.POST)
    public ModelAndView processEditReaderForm(@PathVariable String id,
                                              @ModelAttribute Reader reader, BindingResult bindingResult) {
        ModelAndView results = new ModelAndView("console.editReader");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "firstName", "console.webapp.formValidation.emptyField");
        ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "lastName", "console.webapp.formValidation.emptyField");
        if(bindingResult.hasErrors()) {
            results.addObject("status", "console.webapp.status.correctForm");
            results.addObject("allGroups", bookrService.listGroups());
            results.addObject("allComments", bookrService.listComments());
        } else {
            reader.setLastUpdateDate(new Date());
            bookrService.updateReader(reader);
            results.addObject("status", "console.webapp.status.editSuccess");
            results.addObject("reader", bookrService.loadReaderById(id));
            results.setViewName("console.reader");
        }
        return results;
    }

    @RequestMapping("/readers")
    public ModelAndView listReaders() {
        ModelAndView results = new ModelAndView("console.readers");
        results.addObject("status", "console.webapp.status.ok");
        results.addObject("readers", bookrService.listReaders());
        return results;
    }

    @RequestMapping("/reader/{id}")
    public ModelAndView showReader(@PathVariable String id) {
        ModelAndView results = new ModelAndView("console.reader");
        results.addObject("status", "console.webapp.status.ok");
        results.addObject("reader", bookrService.loadReaderById(id));
        return results;
    }

    @RequestMapping("/reader/{id}/remove")
    public ModelAndView removeReader(@PathVariable String id) {
        ModelAndView results = new ModelAndView("redirect:/readers");
        bookrService.removeReader(bookrService.loadReaderById(id));
        return results;
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss");
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(Group.class, "group", new PropertyEditorSupport(Group.class) {
            @Override
            public void setAsText(String id) {
                setValue(bookrService.loadGroup(id));
            }
        });
        binder.registerCustomEditor(Set.class, "comments", new CustomCollectionEditor(Set.class) {
            @Override
            public Object convertElement(Object element) {
                if(element instanceof String)
                    return bookrService.loadComment((String) element);
                return null;
            }
        });
    }

    public BookrService getBookrService() {
        return bookrService;
    }

    public void setBookrService(BookrService bookrService) {
        this.bookrService = bookrService;
    }
}